﻿using System;
using System.Data;
using System.Collections.Generic;
using System.Text;
using Rison.DataAccess.Common;
using System.Reflection;

namespace Rison.BusinessFacade.Common
{
    public abstract class FacadeBase : IFacade
    {
        private string _message = string.Empty;

        protected DataAccessBase dbHelper = null;
        protected abstract DataAccessBase dbObject { get; }//数据库连接对象

        private List<SqlField> _fields = null;//实体对象的数据字段集合
   
        /// <summary>
        /// 执行数据库操作错误时，返回的错误信息。
        /// </summary>
        public string Message
        {
            get { return _message; }
            set { _message = value; }
        }

        #region "  数据表的主键字段名称（自增长列或字符型列，两者只能同时存在一个）  "
        /// <summary>
        /// 自增长类型的主键字段名称。
        /// </summary>
        protected virtual string identityFieldName
        {
            get { return string.Empty; }
        }

        /// <summary>
        /// 字符型的主键字段名称。
        /// </summary>
        protected virtual string keyFieldName
        {
            get { return string.Empty; }
        }
        #endregion


        #region "  验证当前唯一索引的键值是否已存在  "
        /// <summary>
        /// 验证当前唯一索引的键值是否已存在。仅支持主键是自增长列的情况。
        /// </summary>
        /// <param name="primaryKeyValue">当前的主键值，用来与取得的数据行的主键做验证，是否是自己本身的。</param>
        /// <param name="currentIndexKeyValue">要验证的索引键值</param>
        /// <returns></returns>
        public bool IndexKeyExists(string primaryKeyValue, List<SqlField> indexKeyFields)
        {
            if (indexKeyFields != null)
            {
                DataRow row = dbObject.Retrieve(indexKeyFields);
                if (row != null)
                {
                    return !primaryKeyValue.Equals(row[identityFieldName].ToString());
                }
            }

            return false;
        }
        #endregion


        /// <summary>
        /// 取得对象的数据字段列集合，用于保存和更新。
        /// </summary>
        /// <returns></returns>
        protected abstract List<SqlField> GetSqlFieldCollection(object value, bool getIdentityField);
       

        #region "  save  "
        public virtual long Save(object value)
        {
            _fields = GetSqlFieldCollection(value, false);

            if (_fields == null || _fields.Count == 0)
                return 0;

            this.OnSaving();

            try
            {
                return dbObject.Save(_fields);
            }
            catch (Exception ex)
            {
                if (string.IsNullOrEmpty(dbObject.Message))
                    _message = ex.Message;
                else
                    _message = dbObject.Message;
            }
            finally
            {
                this.OnSaved();
            }            

            return Convert.ToInt64(ErrNumber.Save);
        }
        #endregion


        /// <summary>
        /// 读取到数据行后，将值付给实体对象对应的字段。
        /// </summary>
        /// <param name="row"></param>
        protected abstract object SetPropertiesValue(DataRow row);


        #region "  retrieve  "

        private object SetObjectPropertiesValue(DataRow row)
        {
            if (row != null)
                return SetPropertiesValue(row);
            return null;
        }

        public virtual object Retrieve(int identityValue)
        {
            try
            {
                return SetObjectPropertiesValue(dbObject.Retrieve(identityValue));
            }
            catch { _message = dbObject.Message; }

            return null;
        }

        public virtual object Retrieve(long identityValue)
        {
            try
            {
                return SetObjectPropertiesValue(dbObject.Retrieve(identityValue));
            }
            catch { _message = dbObject.Message; }

            return null;
        }

        public virtual object Retrieve(string keyValue, bool isNumber)
        {
            try
            {
                return SetObjectPropertiesValue(dbObject.Retrieve(keyValue, isNumber));
            }
            catch { _message = dbObject.Message; }

            return null;
        }

        public virtual object Retrieve(string keyname, string keyvalue)
        {
            try
            {
                return SetObjectPropertiesValue(dbObject.Retrieve(keyname, keyvalue));
            }
            catch { _message = dbObject.Message; }

            return null;
        }

        public virtual object Retrieve(List<SqlField> fields)
        {
            try
            {
                return SetObjectPropertiesValue(dbObject.Retrieve(fields));
            }
            catch { if (!string.IsNullOrEmpty(dbObject.Message)) _message = dbObject.Message; }

            return null;
        }
        #endregion


        #region "  update  "
        public virtual int Update(object value)
        {
            _fields = GetSqlFieldCollection(value, true);

            if (_fields == null || _fields.Count == 0)
                return 0;

            this.OnUpdating();
            try
            {
                return dbObject.Update(_fields);
            }
            catch { _message = dbObject.Message; }
            finally { this.OnUpdated(); }

            return Convert.ToInt32(ErrNumber.Update);
        }
        #endregion


        #region "  delete  "
        /// <summary>
        /// 删除数据。主键字段为int型自增长列。
        /// </summary>
        /// <param name="identityValue"></param>
        /// <returns></returns>
        public virtual int Delete(int identityValue)
        {
            return Delete(identityValue.ToString(), true);
        }

        /// <summary>
        /// 删除数据。主键字段为bigint型自增长列。
        /// </summary>
        /// <param name="identityValue"></param>
        /// <returns></returns>
        public virtual int Delete(long identityValue)
        {
            return Delete(identityValue.ToString(), true);
        }

        /// <summary>
        /// 删除数据。主键字段为字符类型。
        /// </summary>
        /// <param name="keyValue"></param>
        /// <returns></returns>
        public virtual int Delete(string keyValue)
        {
            return Delete(keyValue, false);
        }

        /// <summary>
        /// 删除数据。
        /// isNumber的区别在于where语句，value=1 或 value='1'。
        /// </summary>
        /// <param name="keyValue"></param>
        /// <param name="isNumber">关键字字段是否数值类型。</param>
        /// <returns></returns>
        public virtual int Delete(string keyValue, bool isNumber)
        {
            this.OnDeleting();

            try
            {
                return dbObject.Delete(keyValue, isNumber);
            }
            catch (System.Data.SqlClient.SqlException ex)
            {
                if (string.IsNullOrEmpty(dbObject.Message))
                    _message = ex.Message;
                else
                    _message = dbObject.Message;

                return (ex.Number * -1);
            }
            catch (Exception ex)
            {
                if (string.IsNullOrEmpty(dbObject.Message))
                    _message = ex.Message;
                else
                    _message = dbObject.Message;
            }
            finally { this.OnDeleted(); }

            return Convert.ToInt32(ErrNumber.Delete);
        }
        #endregion


        protected virtual void OnSaving()
        {
        }

        protected virtual void OnUpdating()
        {
        }

        protected virtual void OnDeleting()
        {
        }

        protected virtual void OnSaved()
        {
        }

        protected virtual void OnUpdated()
        {
        }

        protected virtual void OnDeleted()
        {
        }


        public virtual DataSet GetAllData()
        {
            try
            {
                return dbObject.GetAllData();
            }
            catch { _message = dbObject.Message; throw; }
        }

        public virtual DataSet GetDataBy(List<Condition> conditions)
        {
            try
            {
                return dbObject.GetDataBy(ConditionConverter.ConvertToSqlConditionString(conditions));
            }
            catch { _message = dbObject.Message; throw; }
        }

        public virtual DataSet GetDataBy(string strCondtion)
        {
            try
            {
                return dbObject.GetDataBy(strCondtion);
            }
            catch { _message = dbObject.Message; throw; }
        }

    }
}
